﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.ServiceProcess;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace ServiceEx
{
    public partial class Form1 : Form
    {
        #region Attributes

        private string[] exePath;
        private string ServiceName = "ServiceEx";
        private string AccountType = "0";
        private string UserName = "LocalSystem";
        private string Pass = "";
        private bool IsInteractive = false;
        private string StartType = "0";
        private string Start = "auto";
        private bool IsStart = false;
        private string LogPath = "";

        #endregion

        #region Form

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            InitForm();
            ReleaseFile();
        }

        private void InitForm()
        {
            QT.IO.XML xml = new QT.IO.XML(Application.StartupPath + @"\ServiceEx.xml");
            exePath = xml.MultiRead("/ServiceEx/ExeList/Path","");
            this.lbExePath.Items.Clear();
            for (int i = 0; exePath!=null&&i < exePath.Length; i++)
            {
                this.lbExePath.Items.Add(exePath[i]);
            }
            this.tbServiceName.Text = xml.Read("/ServiceEx/ServiceName", "");
            this.cbbAccountType.SelectedIndex = int.Parse(xml.Read("/ServiceEx/Account","Type"));
            if (this.cbbAccountType.SelectedIndex == 0)
            {
                this.cbInteractive.Checked = xml.Read("/ServiceEx/Account", "InterActive") == "1" ? true : false;
            }
            if (this.cbbAccountType.SelectedIndex == 3)
            {
                this.tbUserName.Text = xml.Read("/ServiceEx/Account/UserName", "");
                this.tbPass.Text = xml.Read("/ServiceEx/Account/Pass", "");
            }
            this.cbbStartType.SelectedIndex = int.Parse(xml.Read("/ServiceEx/Start", "Type"));
            this.cbStart.Checked = xml.Read("/ServiceEx/Start", "Run") == "1" ? true : false;
            this.tbLogPath.Text = xml.Read("/ServiceEx/LogPath", "");
        }

        #endregion

        #region Button

        private void btnOpenExe_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.FileName = "";
            this.openFileDialog1.Filter = "应用程序|*.exe|所有文件|*.*";
            this.openFileDialog1.FilterIndex = 1;
            this.openFileDialog1.Multiselect = true;
            if (this.openFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            foreach (string file in this.openFileDialog1.FileNames)
            {
                this.lbExePath.Items.Add(file);
            }
        }

        private void btnRemoveExe_Click(object sender, EventArgs e)
        {
            if (this.lbExePath.SelectedItems != null)
            {
                while (this.lbExePath.SelectedItems.Count > 0)
                {
                    this.lbExePath.Items.Remove(this.lbExePath.SelectedItems[0]);
                }
            }
        }

        private void cbbAccountType_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (this.cbbAccountType.SelectedIndex)
            {
                case 0:
                    AccountType = "0";
                    UserName = "LocalSystem";
                    this.cbInteractive.Visible = true;
                    this.pUser.Visible = false;
                    break;
                case 1:
                    AccountType = "1";
                    UserName = "LocalService";
                    this.cbInteractive.Visible = false;
                    this.pUser.Visible = false;
                    break;
                case 2:
                    AccountType = "2";
                    UserName = "NetWorkService";
                    this.cbInteractive.Visible = false;
                    this.pUser.Visible = false;
                    break;
                case 3:
                    AccountType = "3";
                    this.cbInteractive.Visible = false;
                    this.pUser.Visible = true;
                    break;
                default:
                    MessageBox.Show("系统错误");
                    break;
            }

        }

        private void cbbStartType_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (this.cbbStartType.SelectedIndex)
            {
                case 0:
                    StartType = "0";
                    this.cbStart.Visible = true;
                    break;
                case 1:
                    StartType = "1";
                    this.cbStart.Visible = false;
                    break;
                default:
                    MessageBox.Show("系统错误");
                    break;
            }
        }

        private void btnLog_Click(object sender, EventArgs e)
        {
            this.saveFileDialog1.Filter = "日志文件|*.log|文本文件|*.txt";
            this.saveFileDialog1.FilterIndex = 1;
            this.saveFileDialog1.AddExtension = true;
            this.saveFileDialog1.DefaultExt = "log";
            this.saveFileDialog1.FileName = "ServiceEx";
            if (this.saveFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            this.tbLogPath.Text = this.saveFileDialog1.FileName;
        }

        private void btnSetup_Click(object sender, EventArgs e)
        {
            #region 检查数据合法性

            if (this.lbExePath.Items.Count == 0)
            {
                MessageBox.Show("请选择要运行的程序");
                return;
            }
            if (this.cbbAccountType.SelectedIndex == 3 && (this.tbUserName.Text.Trim() == "" || this.tbPass.Text.Trim() == ""))
            {
                MessageBox.Show("请输入运行账户和密码");
                return;
            }
            if (this.tbLogPath.Text.Trim()=="")
            {
                MessageBox.Show("请设置日志路径");
                return;
            }

            #endregion

            #region 初始化数据

            ServiceName = this.tbServiceName.Text;
            exePath=new string[this.lbExePath.Items.Count];
            for (int i = 0; i < this.lbExePath.Items.Count; i++)
            {
                exePath[i] = this.lbExePath.Items[i].ToString();
            }
            AccountType = this.cbbAccountType.SelectedIndex.ToString();
            switch (AccountType)
            {
                case "1":
                    UserName = "LocalService";
                    break;
                case "2":
                    UserName = "NetWorkService";
                    break;
                case "3":
                    UserName = this.tbUserName.Text;
                    Pass = this.tbPass.Text;
                    break;
                default:
                    UserName = "LocalSystem";
                    IsInteractive = this.cbInteractive.Checked;
                    break;
            }
            StartType = this.cbbStartType.SelectedIndex.ToString();
            switch (StartType)
            {
                case "1":
                    Start = "Demand";
                    break;
                default:
                    Start = "Auto";
                    IsStart = this.cbStart.Checked;
                    break;
            }
            LogPath = this.tbLogPath.Text;

            #endregion

            if (CheckService())
            {
                MessageBox.Show("服务名称已存在，请检查");
                return;
            }

            if (!CreateService()) return;
            StartService();
            SaveSetting();
        }

        #endregion

        #region Method

        private bool CheckService()
        {
            ServiceController[] sc = ServiceController.GetServices();

            foreach (ServiceController service in sc)
            {
                if (service.ServiceName.ToUpper() == ServiceName.ToUpper()) return true;
            }

            return false;
        }

        private bool CreateService()
        {
            Process process = new Process();
            try
            {
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.FileName = "sc.exe";
                process.StartInfo.Arguments = " create " + ServiceName + " binPath= \"" + Application.ExecutablePath + " -service\" type= \"share\"" + (IsInteractive ? " type= \"interact\"" : "") + " obj= \"" + UserName + "\"" + (AccountType == "3" ? " password= \"" + Pass + "\"" : "") + " start= \"" + (StartType == "0" ? "auto" : "demand") + "\"";
                process.StartInfo.UseShellExecute = false;
                process.Start();
                string Result = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
            process.Close();
            }

            return CheckService();
        }

        private void StartService()
        {
            if (this.cbStart.Checked)
            {
                ServiceController sc = new ServiceController(ServiceName);
                try
                {
                    sc.Start();
                    sc.WaitForStatus(ServiceControllerStatus.Running);
                    MessageBox.Show("服务状态:" + sc.Status.ToString());
                }
                catch (InvalidOperationException ex)
                {
                    MessageBox.Show(ex.Message);
                    return;
                }
                catch (Exception)
                {
                    MessageBox.Show("系统错误");
                    return;
                }
                finally
                {
                    sc.Dispose();
                }
            }
        }

        private void SaveSetting()
        {
            QT.IO.XML xml = new QT.IO.XML(@".\ServiceEx.xml");
            xml.Update("/ServiceEx/ServiceName", "", ServiceName);
            xml.Delete("/ServiceEx/ExeList", "");
            xml.Insert("/ServiceEx", "ExeList", "", "");
            foreach(string Path in exePath)
            {
                xml.Insert("/ServiceEx/ExeList", "Path", "", Path);
            }
            xml.Update("/ServiceEx/Account", "Type", AccountType);
            xml.Update("/ServiceEx/Account/UserName", "", UserName);
            xml.Update("/ServiceEx/Account/Pass", "", Pass);
            xml.Update("/ServiceEx/Account", "InterActive", IsInteractive ? "1" : "0");
            xml.Update("/ServiceEx/Start", "Type", StartType);
            xml.Update("/ServiceEx/Start", "Run", IsStart ? "1" : "0");
            xml.Update("/ServiceEx/Start", "", Start);
            xml.Update("/ServiceEx/LogPath", "", LogPath);
        }

        #endregion

        #region ReleaseFile

        private void ReleaseFile()
        {
            string AppConfig = @".\ServiceEx.xml";
            if (!File.Exists(AppConfig))
            {
                FileStream FS = null;
                BinaryWriter BWriter = null;
                try
                {
                    byte[] buffer = System.Text.Encoding.Default.GetBytes(Properties.Resources.ServiceEx);
                    FS = new FileStream(AppConfig, FileMode.Create);
                    BWriter = new BinaryWriter(FS);
                    BWriter.Write(buffer, 0, buffer.Length);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    FS.Close();
                }
            }
        }

        #endregion
    }
}
